package org.grow.leave.controller;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.grow.leave.dao.LeaveDao;
import org.grow.leave.entity.*;
import org.grow.leave.entity.enums.ApplyState;
import org.grow.leave.entity.enums.AuditState;
import org.grow.leave.exception.AugustException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

/**
 * @Author: xwg
 * @CreateDate: 21-7-19
 */

@RestController
@RequestMapping("/leave/about")
public class LeaveController {

    @Autowired
    private LeaveDao leaveDao;

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @PostMapping("")
    public Boolean insert(@RequestBody LeaveEntity leaveEntity) {

//        if (leaveEntity.getLeaveId()==10){
//            throw new AugustException("请求参数不合法，返回");
//        }
//        if (leaveEntity.getReason().startsWith("没原因")){
//            throw new AugustException("没原因就不要请假");
//        }
        leaveEntity.setLeaveId(0);

        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        leaveEntity.setApplier(name);
        leaveEntity.setApplyTime(LocalDateTime.now());
        leaveEntity.setAuditorWord(null);
        leaveEntity.setAuditor(null);

        leaveEntity.setApplyState(ApplyState.saved);
        leaveEntity.setAuditState(AuditState.notAudit);
        LeaveEntity save = leaveDao.save(leaveEntity);

        return save.getLeaveId() != 0;
    }

    @PostMapping("/query/apply")
    public PagedResults<LeaveEntity> queryApply(@RequestBody ApplyPagedCondition
                                                        applyPagedCondition) {
        Integer pageNum = applyPagedCondition.getPageNum();
        Integer pageSize = applyPagedCondition.getPageSize();
        Integer pageStart = (pageNum - 1) * pageSize;
        ApplyQueryCondition qc = applyPagedCondition.getQueryCondition();
        QLeaveEntity l = QLeaveEntity.leaveEntity;
//动态条件
        BooleanBuilder builder = new BooleanBuilder();
        /**
         *     private Integer leaveId;
         *     private String auditorSimilar;
         *     private List<ApplyState> applyStates;
         *     private List<LeaveType> leaveTypes;
         *     private LocalDateTime applyTimeEnd;
         *     private LocalDateTime applyTimeStart;
         * */
        if (qc.getLeaveId() != null && qc.getLeaveId() != 0) {

            builder.and(l.leaveId.eq(qc.getLeaveId()));
        }
        if (StringUtils.hasText(qc.getAuditorSimilar())) {

            builder.and(l.auditor.like("%" + qc.getAuditorSimilar() + "%"));
        }
        if (!CollectionUtils.isEmpty(qc.getApplyStates())) {

            builder.and(l.applyState.in(qc.getApplyStates()));
        }
        if (!CollectionUtils.isEmpty(qc.getLeaveTypes())) {

            builder.and(l.leaveType.in(qc.getLeaveTypes()));
        }
//        start    ->   apply   --> end
        if (qc.getApplyTimeStart() != null) {

            builder.and(l.applyTime.after(qc.getApplyTimeStart()));
        }
        if (qc.getApplyTimeEnd() != null) {

            builder.and(l.applyTime.before(qc.getApplyTimeEnd()));
        }

//静态条件

        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        builder.and(l.applier.eq(name));

        QueryResults<LeaveEntity> queryResults = jpaQueryFactory.selectFrom(l)
                .where(builder)
                .orderBy(l.leaveId.desc())
                .offset(pageStart)
                .limit(pageSize)
                .fetchResults();


        PagedResults<LeaveEntity> pagedResults = new PagedResults<>();
        pagedResults.setResults(queryResults.getResults());
        pagedResults.setTotal(queryResults.getTotal());
        return pagedResults;
    }

    @GetMapping("/apply/{leaveId}")
    public LeaveEntity findApply(@PathVariable("leaveId")
                                         Integer leaveId) {


        LeaveEntity entity = leaveDao.findByLeaveId(leaveId);

        if (null == entity) {
            throw new AugustException("没有查询到id " + leaveId + "的数据");
        }

        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        if (!entity.getApplier().equals(name)) {
            throw new AugustException("当前用户" + name + " ,请假条所有人是：" + entity.getApplier() + " 所以无法查看");
        }

//        QLeaveEntity l = QLeaveEntity.leaveEntity;
//        LeaveEntity entity1 = jpaQueryFactory.selectFrom(l)
//        .where(l.leaveId.eq(leaveId)).fetchFirst();

        return entity;

    }


    @PutMapping("/modify")
    public Boolean modify(@RequestBody LeaveEntity leaveEntity) {
        LeaveEntity fromDb = leaveDao.findByLeaveId(leaveEntity.getLeaveId());
        if (fromDb == null) {
            throw new AugustException("待编辑的请假条不存在于数据中，请先新增");
        }
        //未提交未审核状态可以进一步修改请假内容modify未提交未审核状态
        if (leaveEntity.getApplyState() != ApplyState.saved) {
            throw new AugustException("只有未提交未审核状态的请假条才可修改");
        }
        if (leaveEntity.getAuditState() != AuditState.notAudit) {
            throw new AugustException("只有未提交未审核状态的请假条才可修改");
        }

        leaveDao.save(leaveEntity);
        return true;
    }

    //    提交会把申请状态从未提交未审核状态状态变为submmitted已提交未审核状态
    @PutMapping("/submit/{leaveId}")
    public Boolean submit(@PathVariable("leaveId") Integer leaveId) {
        LeaveEntity leaveEntity = leaveDao.findByLeaveId(leaveId);
        if (null == leaveEntity) {
            throw new AugustException("待提交的请假条不存在");
        }
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        if (!leaveEntity.getApplier().equals(name)) {
            throw new AugustException("只有请假人自己才能提交请假条");
        }

        if (leaveEntity.getApplyState() != ApplyState.saved) {
            throw new AugustException("只有未提交未审核状态的请假条才可提交");
        }
        if (leaveEntity.getAuditState() != AuditState.notAudit) {
            throw new AugustException("只有未提交未审核状态的请假条才可提交");
        }

        leaveEntity.setApplyState(ApplyState.submitted);
//        leaveEntity.setAuditState(AuditState.notAudit);
        leaveEntity.setApplyTime(LocalDateTime.now());
        leaveDao.save(leaveEntity);
        return true;

    }

    @PostMapping("/query/audit")
    public PagedResults<LeaveAuditDto> queryAudit(@RequestBody AuditPagedCondition
                                                          auditPagedCondition) {

        AuditQueryCondition qc = auditPagedCondition.getQueryCondition();
        Integer pageNum = auditPagedCondition.getPageNum();
        Integer pageSize = auditPagedCondition.getPageSize();
        Integer pageStart = (pageNum - 1) * pageSize;
        QLeaveEntity l = QLeaveEntity.leaveEntity;
        BooleanBuilder builder = new BooleanBuilder();
        /** qc
         *     private Integer leaveId;
         *     --------------->  start   applyTime  end
         *     private LocalDateTime applyTimeStart;
         *     private LocalDateTime applyTimeEnd;
         *     private List<AuditState> auditStates;
         *     private List<LeaveType> leaveTypes;
         *     private String applierSimilar;
         * */
//        System.out.println(qc);
        if (qc.getLeaveId()!=null && qc.getLeaveId()!=0){

            builder.and(l.leaveId.eq(qc.getLeaveId()));
        }
        if (qc.getApplyTimeStart()!=null){

            builder.and(l.applyTime.after(qc.getApplyTimeStart()));
        }
        if (qc.getApplyTimeEnd()!=null){

            builder.and(l.applyTime.before(qc.getApplyTimeEnd()));
        }
        if (!CollectionUtils.isEmpty(qc.getAuditStates())){

            builder.and(l.auditState.in(qc.getAuditStates()));
        }
        if (!CollectionUtils.isEmpty(qc.getLeaveTypes())){

            builder.and(l.leaveType.in(qc.getLeaveTypes()));
        }
        if (StringUtils.hasText(qc.getApplierSimilar())){

            builder.and(l.applier.like("%" + qc.getApplierSimilar() + "%"));
        }

//        静态部分
        builder.and(l.applyState.eq(ApplyState.submitted));

        /**
         *      private Integer leaveId;
         *     private LeaveType leaveType;
         *     private String reason;
         *     private String applier;
         *     private ApplyState applyState;
         *     private LocalDateTime applyTime;
         *     private AuditState auditState;
         *     private String auditor;
        * */
//
        QueryResults<LeaveAuditDto> queryResults = jpaQueryFactory
                .select(
                        Projections.bean(
                                LeaveAuditDto.class,
                                l.leaveId,
                                l.leaveType,
                                l.reason,
                                l.applier,
                                l.applyState,
                                l.applyTime.as("applyTime"),
                                l.auditState,
                                l.auditor
                        )
                )
                .from(l)
                .where(builder)
                .orderBy(l.applyTime.desc())
                .offset(pageStart)
                .limit(pageSize)
                .fetchResults();
        PagedResults<LeaveAuditDto> pagedResults = new PagedResults<>();
        pagedResults.setTotal(queryResults.getTotal());
        pagedResults.setResults(queryResults.getResults());
        return pagedResults;

    }
//    get  select
//    post insert 复杂查询
//    put  update
//    delete delete/update isDeleted

    @GetMapping("/audit/{leaveId}")
    public LeaveEntity findAudit(@PathVariable("leaveId")
                                 Integer leaveId){
        LeaveEntity en = leaveDao.findByLeaveId(leaveId);
        if (null == en){
            throw new AugustException("没有查询到id " + leaveId + "的数据");
        }
        if (en.getApplyState()!=ApplyState.submitted){
            throw new AugustException("必须是已提交状态的请假条才可以通过本接口查看");
        }
        return en;
    }

//    已提交未审核状态，点击审核通过按钮，状态变为已提交审核通过状态
    @PutMapping("/audit/succeed")
    public Boolean auditSucceed(@RequestBody LeaveEntity
                                            leaveEntity){
        LeaveEntity fromDb = leaveDao.findByLeaveId(leaveEntity.getLeaveId());
        if (null == fromDb){
            throw  new AugustException("数据库里不存在待审核的数据");
        }
//        transform 之前的处理函数
        if (fromDb.getApplyState()!=ApplyState.submitted){
            throw new AugustException("当前请假条不处于已提交未审核状态，故而不能审核通过");
        }
        if (fromDb.getAuditState()!=AuditState.notAudit){
            throw new AugustException("当前请假条不处于已提交未审核状态，故而不能审核通过");
        }
//        核心状态改变语句
//        fromDb.setApplyState(ApplyState.submitted);
        fromDb.setAuditState(AuditState.auditSucceed);

//        状态改变后的处理函数
        fromDb.setAuditorWord(leaveEntity.getAuditorWord());
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        fromDb.setAuditor(name);
        leaveDao.save(fromDb);
//
//        信赖前端数据下的代码，比较简单，安全性稍差。
//        String name = SecurityContextHolder.getContext().getAuthentication().getName();
//        leaveEntity.setAuditor(name);
//        leaveDao.save(leaveEntity);

        return true;
    }

    //    已提交未审核状态，点击审核不通过按钮，状态变为已提交审核不通过状态
    @PutMapping("/audit/failed")
    public Boolean auditFailed(@RequestBody LeaveEntity
                                           leaveEntity){
        LeaveEntity fromDb = leaveDao.findByLeaveId(leaveEntity.getLeaveId());
        if (null == fromDb){
            throw new AugustException("数据库中不存在此数据");
        }
//        转变前置函数
        if (fromDb.getAuditState()!=AuditState.notAudit){
            throw new AugustException("当前请假条不处于已提交未审核状态，故而不能审核不通过");
        }
        if (fromDb.getApplyState()!=ApplyState.submitted){
            throw new AugustException("当前请假条不处于已提交未审核状态，故而不能审核不通过");
        }
//        A B状态转变函数
        fromDb.setApplyState(ApplyState.submitted);
        fromDb.setAuditState(AuditState.auditFailed);
//        转变后置函数
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        fromDb.setAuditor(name);
        fromDb.setAuditorWord(leaveEntity.getAuditorWord());
        leaveDao.save(fromDb);
        return true;



//        String name = SecurityContextHolder.getContext().getAuthentication().getName();
//        leaveEntity.setAuditor(name);
//        leaveDao.save(leaveEntity);
    }

//    已提交审核通过或审核不通过状态 -》确认 -》已终结审核通过或审核不通过状态
//   未审核状态不能确认
    @PutMapping("/confirm/{leaveId}")
    public Boolean confirm(@PathVariable("leaveId")Integer leaveId){
        LeaveEntity leaveEntity = leaveDao.findByLeaveId(leaveId);
        if (null == leaveEntity){
            throw new AugustException("数据库不存在该数据");
        }
//        前置判断
        if (leaveEntity.getApplyState()!=ApplyState.submitted){
            throw new AugustException("当前请假条不处于已提交状态，故而不能确认审核结果");
        }

        Boolean a = false;
        if (leaveEntity.getAuditState() == AuditState.auditSucceed){
            a = true;
        }
        if (leaveEntity.getAuditState() == AuditState.auditFailed){
            a = true;
        }
        if (!a){
            throw new AugustException("当前请假条没有被审核过，所以不能确认审核结果");
        }


        leaveEntity.setApplyState(ApplyState.ended);

//        后置处理函数

        leaveDao.save(leaveEntity);
        return true;
    }
}
